package com.zjw.algorithm;

import com.zjw.algorithm.utils.Utils;

import java.util.Arrays;

/**
 * 根据 百度百科 ， 生命游戏 ，简称为 生命 ，是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
 * <p>
 * 给定一个包含 m × n 个格子的面板，每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态： 1 即为 活细胞 （live），或 0 即为 死细胞 （dead）。每个细胞与其八个相邻位置（水平，垂直，对角线）的细胞都遵循以下四条生存定律：
 * <p>
 * 如果活细胞周围八个位置的活细胞数少于两个，则该位置活细胞死亡；
 * 如果活细胞周围八个位置有两个或三个活细胞，则该位置活细胞仍然存活；
 * 如果死细胞周围正好有三个活细胞，则该位置死细胞复活；
 * 如果活细胞周围八个位置有超过三个活细胞，则该位置活细胞死亡；
 * 下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的，其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态，返回下一个状态。
 */
public class Solution12 {

    public static void main(String[] args) {
        int[][] board = Utils.createTwoDimensionArrayFromOneDimension(new int[]{0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, 3);

        System.out.println(Arrays.deepToString(board));
        new Solution12().gameOfLife(board);

        System.out.println(Arrays.deepToString(board));
    }

    public void gameOfLife(int[][] board) {
        int height = board.length;
        int width = board[0].length;

        int[][] nextState = new int[height][];

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int lifeCountOfAround = getLifeCountOfAround(board, i, j);
                int selfState = board[i][j];

                if (nextState[i] == null) {
                    nextState[i] = new int[width];
                }

                if (selfState == 1) {
                    if (lifeCountOfAround < 2) {
                        nextState[i][j] = 0;
                    } else if (lifeCountOfAround == 2 || lifeCountOfAround == 3) {
                        nextState[i][j] = 1;
                    } else {
                        nextState[i][j] = 0;
                    }
                } else {
                    if (lifeCountOfAround == 3) {
                        nextState[i][j] = 1;
                    }
                }
            }
        }

        for (int i = 0; i < height; i++) {
            System.arraycopy(nextState[i], 0, board[i], 0, width);
        }
    }


    public int getLifeCountOfAround(int[][] board, int i, int j) {
        int count = 0;

        if (i - 1 >= 0 && j - 1 >= 0) {
            count += board[i - 1][j - 1];
        }
        if (i - 1 >= 0 && j + 1 < board[i - 1].length) {
            count += board[i - 1][j + 1];
        }

        if (i - 1 >= 0 && j < board[i - 1].length) {
            count += board[i - 1][j];
        }

        if (i + 1 < board.length && j - 1 >= 0) {
            count += board[i + 1][j - 1];
        }
        if (i + 1 < board.length && j + 1 < board[i + 1].length) {
            count += board[i + 1][j + 1];
        }

        if (i + 1 < board.length && j < board[i + 1].length) {
            count += board[i + 1][j];
        }

        if (j - 1 >= 0) {
            count += board[i][j - 1];
        }
        if (j + 1 < board[i].length) {
            count += board[i][j + 1];
        }

        return count;
    }


}
